#pragma once

#include "Base/Engine.Base.h"


using namespace Engine;
using namespace Base;

#undef  APP_NAME
#define APP_NAME	TestApp
#undef  APP_BASE
#define APP_BASE	Application


class APP_NAME : public APP_BASE
{
public:
	typedef SHARED_POINTER_TYPE( APP_NAME )	TestAppPtr;

	APP_NAME (IPlatform *platform, EDevice::type deviceType) :
		APP_BASE( platform, deviceType )
	{
		ESS()->GetEventSystem()->AttachEventListener(
			DelegateBuilder::Create( TestAppPtr(this), &APP_NAME::_OnAppEvent ),	ESystemEvent::APPLICATION );

		ESS()->GetEventSystem()->AttachEventListener(
			DelegateBuilder::Create( TestAppPtr(this), &APP_NAME::_OnUpdate ),		ESystemEvent::UPDATE );
		
		DESCTOP_ONLY(
			ESS()->GetFileSystem()->FindAndSetCurrentDir( "Engine/_data", 6 );
		)
	}

	~APP_NAME ()
	{
		ESS()->GetEventSystem()->DetachEventListener(
			DelegateBuilder::Create( TestAppPtr(this), &APP_NAME::_OnAppEvent ),	ESystemEvent::APPLICATION );

		ESS()->GetEventSystem()->DetachEventListener(
			DelegateBuilder::Create( TestAppPtr(this), &APP_NAME::_OnUpdate ),		ESystemEvent::UPDATE );
	}
	
	virtual void Update (float dt)
	{
		if ( ESS()->GetInput()->IsKeyClicked( EKey::BACK ) )
		{
			GetPlatform()->Terminate();
		}
	}

	virtual void OnEnter ()
	{
	}

	virtual void OnExit ()
	{
	}
	
	void _OnUpdate (const SysEvent &ev)
	{
		GetSubSystems()->GetInput()->PreUpdate();
		Update( ev.update.timeDelta );
		GetSubSystems()->GetInput()->PostUpdate();
		Thread::Yield();
	}
	
	void _OnAppEvent (const SysEvent &ev)
	{
#		define WARN( _text )			LOG( _text, ELog::DEBUG )

		switch ( ev.app.type )
		{
			case SysEvent::Application::CREATED :
				WARN( "Application Created" );
				break;
				
			case SysEvent::Application::DESTROY :
				WARN( "Application Destroy" );
				break;
				
			case SysEvent::Application::ENTER_BACKGROUND :
				WARN( (string("Application Enter Background ") << (ev.app.completed ? "completed" : "")).cstr() );

				if ( not ev.app.completed )
					OnExit();
				break;
				
			case SysEvent::Application::ENTER_FOREGROUND :
				WARN( (string("Application Enter Foreground ") << (ev.app.completed ? "completed" : "")).cstr() );

				if ( ev.app.completed )
					OnEnter();
				break;
				
			case SysEvent::Application::SURFACE_CREATED :
				WARN( "Application Surface Created" );
				break;
				
			case SysEvent::Application::SURFACE_DESTROYED :
				WARN( "Application Surface Destroyed" );
				break;
				
			case SysEvent::Application::LOW_MEMORY :
				WARN( "Application Low Memory" );
				break;
		}

#		undef WARN
	}

	template <typename T>
	static void CreateApplication (IPlatform *platform, EDevice::type deviceType, IApplication *&app)
	{
		app = new T( platform, deviceType );
	}
};